/*
 * Copyright 2010 Electronic Business Systems Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package gr.ebs.gssdroid.resource;



import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;


/**
 * @author kman
 */
public class FolderResource extends RestResource {

	public FolderResource(String aUri) {
		super(aUri);
	}

	String name;

	String owner;

	String createdBy;

	String modifiedBy;

	Date creationDate;

	Date modificationDate;

	List<String> filePaths = new LinkedList<String>();

	List<String> subfolderPaths = new LinkedList<String>();

	Set<PermissionHolder> permissions = new HashSet<PermissionHolder>();

	List<FolderResource> folders = new ArrayList<FolderResource>();

	List<FileResource> files = new ArrayList<FileResource>();

	String parentURI;

	boolean deleted = false;

	boolean needsExpanding = false;

	String parentName;

	private boolean filesExpanded=false;
	
	boolean readForAll;
	/**
	 * Modify the parentName.
	 *
	 * @param aParentName the parentName to set
	 */
	public void setParentName(String aParentName) {
		parentName = aParentName;
	}

	/**
	 * Retrieve the name.
	 *
	 * @return the name
	 */
	public String getName() {
		return name;
	}

	/**
	 * Modify the name.
	 *
	 * @param aName the name to set
	 */
	public void setName(String aName) {
		name = aName;
	}

	/**
	 * Retrieve the owner.
	 *
	 * @return the owner
	 */
	public String getOwner() {
		return owner;
	}

	/**
	 * Modify the owner.
	 *
	 * @param anOwner the owner to set
	 */
	public void setOwner(String anOwner) {
		owner = anOwner;
	}

	/**
	 * Retrieve the createdBy.
	 *
	 * @return the createdBy
	 */
	public String getCreatedBy() {
		return createdBy;
	}

	/**
	 * Modify the createdBy.
	 *
	 * @param aCreatedBy the createdBy to set
	 */
	public void setCreatedBy(String aCreatedBy) {
		createdBy = aCreatedBy;
	}

	/**
	 * Retrieve the modifiedBy.
	 *
	 * @return the modifiedBy
	 */
	public String getModifiedBy() {
		return modifiedBy;
	}

	/**
	 * Modify the modifiedBy.
	 *
	 * @param aModifiedBy the modifiedBy to set
	 */
	public void setModifiedBy(String aModifiedBy) {
		modifiedBy = aModifiedBy;
	}

	/**
	 * Retrieve the creationDate.
	 *
	 * @return the creationDate
	 */
	public Date getCreationDate() {
		return creationDate;
	}

	/**
	 * Modify the creationDate.
	 *
	 * @param aCreationDate the creationDate to set
	 */
	public void setCreationDate(Date aCreationDate) {
		creationDate = aCreationDate;
	}

	/**
	 * Retrieve the modificationDate.
	 *
	 * @return the modificationDate
	 */
	public Date getModificationDate() {
		return modificationDate;
	}

	/**
	 * Modify the modificationDate.
	 *
	 * @param aModificationDate the modificationDate to set
	 */
	public void setModificationDate(Date aModificationDate) {
		modificationDate = aModificationDate;
	}

	/**
	 * Retrieve the filePaths.
	 *
	 * @return the filePaths
	 */
	public List<String> getFilePaths() {
		return filePaths;
	}

	/**
	 * Modify the filePaths.
	 *
	 * @param newFilePaths the filePaths to set
	 */
	public void setFilePaths(List<String> newFilePaths) {
		filePaths = newFilePaths;
	}

	/**
	 * Retrieve the subfolderPaths.
	 *
	 * @return the subfolderPaths
	 */
	public List<String> getSubfolderPaths() {
		return subfolderPaths;
	}

	public List<Long> getModified(){
		List<Long> res = new ArrayList();
		for(FolderResource r : getFolders())
			if(r.getModificationDate() != null)
				res.add(r.getModificationDate().getTime());
			else
				res.add(new Date().getTime());
		return res;
	}
	/**
	 * Modify the subfolderPaths.
	 *
	 * @param newSubfolderPaths the subfolderPaths to set
	 */
	public void setSubfolderPaths(List<String> newSubfolderPaths) {
		subfolderPaths = newSubfolderPaths;
	}

	/**
	 * Retrieve the permissions.
	 *
	 * @return the permissions
	 */
	public Set<PermissionHolder> getPermissions() {
		return permissions;
	}

	/**
	 * Modify the permissions.
	 *
	 * @param newPermissions the permissions to set
	 */
	public void setPermissions(Set<PermissionHolder> newPermissions) {
		permissions = newPermissions;
	}

	/**
	 * Retrieve the deleted.
	 *
	 * @return the deleted
	 */
	public boolean isDeleted() {
		return deleted;
	}

	/**
	 * Modify the deleted.
	 *
	 * @param newDeleted the deleted to set
	 */
	public void setDeleted(boolean newDeleted) {
		deleted = newDeleted;
	}

	public void removeSubfolderPath(String spath) {
		if (subfolderPaths.remove(spath))
			return;
		else if (subfolderPaths.remove(spath + "/"))
			return;
		else
			subfolderPaths.remove(spath.substring(0, spath.length() - 1));
	}

	/**
	 * Retrieve the folders.
	 *
	 * @return the folders
	 */
	public List<FolderResource> getFolders() {
		return folders;
	}

	/**
	 * Modify the folders.
	 *
	 * @param newFolders the folders to set
	 */
	public void setFolders(List<FolderResource> newFolders) {
		folders = newFolders;
	}

	/**
	 * Retrieve the files.
	 *
	 * @return the files
	 */
	public List<FileResource> getFiles() {
		return files;
	}

	/**
	 * Modify the files.
	 *
	 * @param newFiles the files to set
	 */
	public void setFiles(List<FileResource> newFiles) {
		files = newFiles;
	}

	/**
	 * Retrieve the parentURI.
	 *
	 * @return the parentURI
	 */
	public String getParentURI() {
		return parentURI;
	}

	/**
	 * Modify the parentURI.
	 *
	 * @param aParentURI the parentURI to set
	 */
	public void setParentURI(String aParentURI) {
		parentURI = aParentURI;
	}
	
	public void setReadForAll(boolean readForAll) {
		this.readForAll = readForAll;
	}
	
	public boolean isReadForAll() {
		return readForAll;
	}

	@Override
	public void createFromJSON(String text) throws JSONException {
		JSONObject json = new JSONObject(text);
		name = unmarshallString(json, "name");
		owner = unmarshallString(json, "owner");
		createdBy = unmarshallString(json, "createdBy");
		modifiedBy = unmarshallString(json, "modifiedBy");
		deleted = unmarshallBoolean(json, "deleted");
		readForAll = unmarshallBoolean(json, "readForAll");
		JSONObject parent = getJSONObject(json, "parent");
		if (parent != null) {
			parentURI = unmarshallString(parent, "uri");
			parentName = unmarshallString(parent, "name");
		}
		JSONArray perm = getJSONArray(json, "permissions");
		if (perm != null) {
				for (int i = 0; i < perm.length(); i++) {
					JSONObject obj = perm.getJSONObject(i);
					if (obj != null) {
						PermissionHolder permission = new PermissionHolder();
						String user = unmarshallString(obj, "user");
						if (user != null)
							permission.setUser(unmarshallString(obj, "user"));
						String group = unmarshallString(obj, "groupUri");
						if (group != null) {
							group = URLDecoder.decode(group);
							permission.setGroup(group);
						}
						else{
							group = unmarshallString(obj, "group");
							if(group!=null){
								group = URLDecoder.decode(group);
								permission.setGroup(group);
							}
						}
						permission.setRead(unmarshallBoolean(obj, "read"));
						permission.setWrite(unmarshallBoolean(obj, "write"));
						permission.setModifyACL(unmarshallBoolean(obj, "modifyACL"));
						permissions.add(permission);
					}
				}

		}
			JSONArray subs = getJSONArray(json, "folders");
			if (subs != null)
				for (int i = 0; i < subs.length(); i++) {
					JSONObject so = subs.getJSONObject(i);
					if (so != null) {
						String subUri = unmarshallString(so, "uri");
						String subName = unmarshallString(so, "name");
						String testString = unmarshallString(so, "creationDate");
						if (testString != null)
							creationDate = new Date(new Long(testString));
						testString = unmarshallString(so, "modificationDate");
						if (testString != null)
							modificationDate = new Date(new Long(testString));
						if (subUri != null && subName != null) {
							if (!subUri.endsWith("/"))
								subUri = subUri + "/";
							FolderResource sub = new FolderResource(subUri);
							sub.setName(subName);
							sub.setParentURI(uri);
							sub.setParentName(name);
							sub.setNeedsExpanding(true);
							folders.add(sub);
							subfolderPaths.add(subUri);
						}
					}
				}
			subs = getJSONArray(json, "files");
			if (subs != null)
				for (int i = 0; i < subs.length(); i++) {
					JSONObject fo = subs.getJSONObject(i);
					if (fo != null) {
						String fname = unmarshallString(fo, "name");
						String fowner = unmarshallString(fo, "owner");
						String fcontent = unmarshallString(fo, "content");
						String fpath = unmarshallString(fo, "path");
						fpath = URLDecoder.decode(fpath);
						Integer fversion = null;
						String versionString = unmarshallString(fo, "version");
						if (versionString != null)
							fversion = new Integer(versionString);
						boolean fdeleted = unmarshallBoolean(fo, "deleted");
						Boolean fversioned = false;
						Boolean fshared = false;
						try{
							fversioned=unmarshallBoolean(fo, "versioned");
							fshared = unmarshallBoolean(fo, "shared");
						}
						catch(NullPointerException ex){
							
						}
						String testString = unmarshallString(fo, "creationDate");
						Date fcreationDate = null;
						Date fmodificationDate = null;
						if (testString != null)
							fcreationDate = new Date(new Long(testString));
						testString = unmarshallString(fo, "modificationDate");
						if (testString != null)
							fmodificationDate = new Date(new Long(testString));
						String furi = unmarshallString(fo, "uri");
						Long fsize = 0L;
						testString = unmarshallString(fo, "size");
						if (testString != null)
							fsize = new Long(testString);
						filePaths.add(furi);
						FileResource fs = new FileResource(furi);
						fs.setName(fname);
						fs.setOwner(fowner);
						fs.setPath(fpath);
						fs.setVersion(fversion);
						fs.setContentLength(fsize);
						fs.setDeleted(fdeleted);
						fs.setCreationDate(fcreationDate);
						fs.setModificationDate(fmodificationDate);
						fs.setContentType(fcontent);
						if(fshared!=null)
							fs.setShared(fshared);
						if(fversioned!=null)
							fs.setVersioned(fversioned);
						files.add(fs);
					}
				}
		
		String testString = unmarshallString(json, "creationDate");
		if (testString != null)
			creationDate = new Date(new Long(testString));
		testString = unmarshallString(json, "modificationDate");
		if (testString != null)
			modificationDate = new Date(new Long(testString));
	}

	public String getParentName(){
		return parentName;
	}

	/**
	 * Retrieve the needsExpanding.
	 *
	 * @return the needsExpanding
	 */
	public boolean isNeedsExpanding() {
		return needsExpanding;
	}

	/**
	 * Modify the needsExpanding.
	 *
	 * @param newNeedsExpanding the needsExpanding to set
	 */
	public void setNeedsExpanding(boolean newNeedsExpanding) {
		needsExpanding = newNeedsExpanding;
	}

	public boolean isShared(){

		for(PermissionHolder perm : permissions){
			if(perm.getUser() != null && !owner.equals(perm.getUser()))
				return true;
			if(perm.getGroup() != null)
				return true;
		}
		return false;
	}

	@Override
	public String getLastModifiedSince() {
		if(modificationDate != null)
			return getDate(modificationDate.getTime());
		return null;
	}

	


	public void setFilesExpanded(boolean newFilesExpanded) {
		filesExpanded = newFilesExpanded;
	}
}
